package com.meatball.dronefly;

import androidx.appcompat.app.AppCompatActivity;

import android.app.AlertDialog;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Objects;

import dji.common.error.DJIError;
import dji.common.util.CommonCallbacks;
import dji.sdk.base.BaseProduct;
import dji.sdk.flightcontroller.FlightController;
import dji.sdk.products.Aircraft;
import dji.sdk.sdkmanager.DJISDKManager;

/**
 * 飞行控制类
 * @author 张翔宇
 * @since 2022年8月30日
 */
public class FlightActivity extends AppCompatActivity implements View.OnClickListener {
    /**
     * 声明按钮对象
     */
    private Button mBtnTakeoff, mBtnCancelTakeoff, mBtnLanding, mBtnCancelLanding, mBtnSetGoHomeHeight,
        mBtnGetGoHomeHeight, mBtnGoHome, mBtnCancelGoHome;
    /**
     * 声明显示文本对象
     */
    private TextView mTvMode, mTvLocation, mTvVelocity, mTvSatelliteCount;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flight);
        // 初始化UI界面
        initUI();
        // 初始化监听器
        initListener();
    }

    /**
     * 初始化UI界面
     */
    private void initUI() {
        // 飞行控制
        mBtnTakeoff = findViewById(R.id.btn_takeoff);
        mBtnCancelTakeoff = findViewById(R.id.btn_takeoff_cancel);
        mBtnLanding = findViewById(R.id.btn_landing);
        mBtnCancelLanding = findViewById(R.id.btn_landing_cancel);
        mBtnSetGoHomeHeight = findViewById(R.id.btn_set_go_home_height);
        mBtnGetGoHomeHeight = findViewById(R.id.btn_get_go_home_height);
        mBtnGoHome = findViewById(R.id.btn_go_home);
        mBtnCancelGoHome = findViewById(R.id.btn_go_home_cancel);
        // 飞行状态
        mTvMode = findViewById(R.id.tv_mode);
        mTvLocation = findViewById(R.id.tv_location);
        mTvVelocity = findViewById(R.id.tv_velocity);
        mTvSatelliteCount = findViewById(R.id.tv_satellite_count);
    }

    /**
     * 初始化监听器
     */
    private void initListener() {
        mBtnTakeoff.setOnClickListener(this);
        mBtnCancelTakeoff.setOnClickListener(this);
        mBtnLanding.setOnClickListener(this);
        mBtnCancelLanding.setOnClickListener(this);
        mBtnSetGoHomeHeight.setOnClickListener(this);
        mBtnGetGoHomeHeight.setOnClickListener(this);
        mBtnGoHome.setOnClickListener(this);
        mBtnCancelGoHome.setOnClickListener(this);
        // 飞行状态
        final FlightController controller = getFlightController();
        if (controller != null) {
            // 设置飞行控制器 FlightControllerState 的回调
            controller.setStateCallback(state -> {
                // 获取飞行模式
                final String flightMode = state.getFlightModeString();
                // 获取无人机的高度
                final double altitude = state.getAircraftLocation().getAltitude();
                // 获取无人机的经度
                final double longitude = state.getAircraftLocation().getLongitude();
                // 获取无人机的纬度
                final double latitude = state.getAircraftLocation().getLatitude();
                // 获取无人机X方向的移动速度
                final double velocityX = state.getVelocityX();
                // 获取无人机Y方向的移动速度
                final double velocityY = state.getVelocityY();
                // 获取无人机Z方向的移动速度
                final double velocityZ = state.getVelocityZ();
                // 获取连接卫星的数量
                final int satelliteCount = state.getSatelliteCount();
                // 更新状态信息
                runOnUiThread(() ->{
                    // mTvMode.setText("飞行模式：" + flightMode);
                    mTvMode.setText(String.format(getString(R.string.tv_mode_1), flightMode));
                    mTvLocation.setText(String.format(getString(R.string.tv_location_1), longitude, latitude, altitude));
                    mTvVelocity.setText(String.format(getString(R.string.tv_velocity_1), velocityX, velocityY, velocityZ));
                    mTvSatelliteCount.setText(String.format(getString(R.string.tv_satellite_count_1), satelliteCount));
                });
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_takeoff) {
            takeoff();
        } else if (id == R.id.btn_takeoff_cancel) {
            cancelTakeoff();
        } else if (id == R.id.btn_landing) {
            landing();
        } else if (id == R.id.btn_landing_cancel) {
            cancelLanding();
        } else if (id == R.id.btn_set_go_home_height) {
            setGoHomeHeight();
        } else if (id == R.id.btn_get_go_home_height) {
            getGoHomeHeight();
        } else if (id == R.id.btn_go_home) {
            goHome();
        } else if (id == R.id.btn_go_home_cancel) {
            cancelGoHome();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 移除监听器
        removeListener();
    }

    /**
     * 移除监听器
     */
    private void removeListener() {
        FlightController controller = getFlightController();
        if (controller != null) {
            controller.setStateCallback(null);
        }
    }

    /**
     * 起飞
     */
    private void takeoff() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.startTakeoff(djiError -> {
                if (Objects.nonNull(djiError)) {
                    showToast(djiError.toString());
                } else {
                    showToast("开始起飞。");
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 取消起飞
     */
    private void cancelTakeoff() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.cancelTakeoff(djiError -> {
                if (Objects.nonNull(djiError)) {
                    showToast(djiError.toString());
                } else {
                    showToast("取消起飞成功。");
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 降落
     */
    private void landing() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.startLanding(djiError -> {
                if (Objects.nonNull(djiError)) {
                    showToast(djiError.toString());
                } else {
                    showToast("开始降落。");
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 取消降落
     */
    private void cancelLanding() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.cancelLanding(djiError -> {
                if (Objects.nonNull(djiError)) {
                    showToast(djiError.toString());
                } else {
                    showToast("取消降落成功。");
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 设置返航高度
     */
    private void setGoHomeHeight() {
        // 返航高度设置文本框
        final EditText editText = new EditText(this);
        // 限制只能输入纯数字
        editText.setInputType(InputType.TYPE_CLASS_NUMBER);
        // 弹出返航高度对话框
        new AlertDialog.Builder(this)
                .setTitle("请输入返航高度(m)")
                .setView(editText)
                .setPositiveButton("确定", (dialog, which) -> {
                    // 获取返航高度的设置
                    int height = Integer.parseInt(editText.getText().toString());
                    final FlightController controller = getFlightController();
                    if (controller != null) {
                        // 设置返航高度
                        controller.setGoHomeHeightInMeters(height, djiError -> {
                            if (Objects.nonNull(djiError)) {
                                showToast(djiError.toString());
                            } else {
                                showToast("返航高度设置成功。");
                            }
                        });
                    } else {
                        showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
                    }
                })
                .setNegativeButton("取消", null)
                .show();
    }

    /**
     * 获取返航高度
     */
    private void getGoHomeHeight() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.getGoHomeHeightInMeters(new CommonCallbacks.CompletionCallbackWith<Integer>() {
                @Override
                public void onSuccess(Integer height) {
                    showToast("返航高度为：" + height + "米");
                }

                @Override
                public void onFailure(DJIError djiError) {
                    showToast("返航高度获取失败：" + djiError.toString());
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 返航
     */
    private void goHome() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.startGoHome(djiError -> {
                if (Objects.nonNull(djiError)) {
                    showToast(djiError.toString());
                } else {
                    showToast("开始返航。");
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 取消返航
     */
    private void cancelGoHome() {
        final FlightController controller = getFlightController();
        if (controller != null) {
            controller.cancelGoHome(djiError -> {
                if (Objects.nonNull(djiError)) {
                    showToast(djiError.toString());
                } else {
                    showToast("取消返航成功。");
                }
            });
        } else {
            showToast("飞行控制器获取失败，请检查飞行控制器连接是否正常。");
        }
    }

    /**
     * 获取无人机的飞行控制器
     * @return 飞行控制器
     */
    private FlightController getFlightController() {
        BaseProduct product = DJISDKManager.getInstance().getProduct();
        if (product != null && product.isConnected()) {
            if (product instanceof Aircraft) {
                return ((Aircraft) product).getFlightController();
            }
        }
        return null;
    }

    /**
     * 在主线程中提示
     * @param toastMsg 消息
     */
    private void showToast(final String toastMsg) {
        runOnUiThread(() -> Toast.makeText(getApplicationContext(), toastMsg, Toast.LENGTH_SHORT).show());
    }
}